package ocr

import (
	"encoding/json"
	ocrApi "github.com/alibabacloud-go/ocr-api-20210707/client"
	"github.com/alibabacloud-go/tea/tea"
)

var ocrHost = "https://ocrdiy.market.alicloudapi.com"
var ocrPath = "/api/predict/ocr_sdt"
var ocrAppCode = "b3646e624f28414090e894746b97a895"

type AliOcrFactory struct{}

const (
	BusinessOcr    = 0 // 营业执照识别
	AccountOcr     = 1 // 基本存款账户信息
	IdCardFrontOcr = 2 // 身份证正面识别
	IdCardBackOcr  = 3 // 身份证反面识别
	BankCardOcr    = 4 // 银行卡识别
)

func (aof *AliOcrFactory) New(typ int) AliOcrService {
	switch typ {
	case BusinessOcr:
		return new(BusinessOcrResult)
	case AccountOcr:
		return new(NullResult)
	case IdCardFrontOcr:
		return new(IdCardFrontOcrResult)
	case IdCardBackOcr:
		return new(IdCardBackOcrResult)
	case BankCardOcr:
		return new(BankOcrResult)
	default:
		return new(NullResult)
	}
}

type AliOcrService interface {
	DoOcr(url string) (any, error)
}

// BusinessOcrResult 营业执照
type BusinessOcrResult struct {
	Data struct {
		CreditCode        string `json:"creditCode"`        // 统一社会信用代码
		CompanyName       string `json:"companyName"`       // 营业名称
		CompanyType       string `json:"companyType"`       // 类型
		BusinessAddress   string `json:"businessAddress"`   // 营业场所/住所
		LegalPerson       string `json:"legalPerson"`       // 法人/负责人
		BusinessScope     string `json:"businessScope"`     // 经营范围
		RegisteredCapital string `json:"registeredCapital"` // 注册资本
		RegistrationDate  string `json:"RegistrationDate"`  // 注册日期
		ValidPeriod       string `json:"validPeriod"`       // 营业期限
		ValidFromDate     string `json:"validFromDate"`     // 格式化营业期限起始日期
		ValidToDate       string `json:"validToDate"`       // 格式化营业期限终止日期
	} `json:"data"`
}

func (b *BusinessOcrResult) DoOcr(url string) (any, error) {
	req := &ocrApi.RecognizeBusinessLicenseRequest{
		Url: tea.String(url),
	}

	respData, err := doClientRequest(req, BusinessOcr)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal([]byte(respData), b)
	if err != nil {
		return nil, err
	}

	return b.Data, nil
}

// IdCardFrontOcrResult 身份证正面
type IdCardFrontOcrResult struct {
	Data struct {
		Face struct {
			Data struct {
				Name      string `json:"name"`      // 姓名
				Sex       string `json:"sex"`       // 性别
				Ethnicity string `json:"ethnicity"` // 民族
				BirthDate string `json:"birthDate"` // 出生日期
				Address   string `json:"address"`   // 住址
				IdNumber  string `json:"idNumber"`  // 身份证号码
				Type      string `json:"type"`      // 身份证类型 (正面：face，背面：back)
			} `json:"data"`
		} `json:"face"`
	} `json:"data"`
}

func (f *IdCardFrontOcrResult) DoOcr(url string) (any, error) {
	req := &ocrApi.RecognizeIdcardRequest{
		Url: tea.String(url),
	}

	respData, err := doClientRequest(req, IdCardFrontOcr)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal([]byte(respData), f)
	if err != nil {
		return nil, err
	}

	return f.Data.Face.Data, nil
}

// IdCardBackOcrResult 身份证反面
type IdCardBackOcrResult struct {
	Data struct {
		Back struct {
			Data struct {
				IssueAuthority string `json:"issueAuthority"`
				ValidPeriod    string `json:"validPeriod"`
			} `json:"data"`
		} `json:"back"`
	} `json:"data"`
}

func (b *IdCardBackOcrResult) DoOcr(url string) (any, error) {
	req := &ocrApi.RecognizeIdcardRequest{
		Url: tea.String(url),
	}

	respData, err := doClientRequest(req, IdCardBackOcr)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal([]byte(respData), b)
	if err != nil {
		return nil, err
	}

	return b.Data.Back.Data, nil
}

// BankOcrResult 银行卡
type BankOcrResult struct {
	Data struct {
		BankName    string `json:"bankName"`    // 银行
		CardNumber  string `json:"cardNumber"`  // 银行卡号
		ValidToDate string `json:"validToDate"` // 有效期至
		CardType    string `json:"cardType"`    // 卡种
	} `json:"data"`
}

func (b *BankOcrResult) DoOcr(url string) (any, error) {
	req := &ocrApi.RecognizeBankCardRequest{
		Url: tea.String(url),
	}

	respData, err := doClientRequest(req, BankCardOcr)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal([]byte(respData), b)
	if err != nil {
		return nil, err
	}

	return b.Data, nil
}

// NullResult 空识别
type NullResult struct {
}

func (n *NullResult) DoOcr(url string) (any, error) {
	return nil, nil
}

// TemplateResult 模版识别
type TemplateResult struct {
}

func (t *TemplateResult) DoOcr(url string) (any, error) {
	image, err := copyURLToImage(url)
	if err != nil {
		return nil, err
	}

	body := map[string]interface{}{
		"image": image,
		// 模版ID
	}

	bytesBody, err := json.Marshal(body)
	if err != nil {
		return nil, err
	}

	resp, err := doHttpRequest(ocrHost+ocrPath, string(bytesBody), "application/json")
	if err != nil || resp == nil {
		return nil, err
	}

	err = json.Unmarshal(resp, t)
	if err != nil {
		return nil, err
	}

	return t, nil
}
